package org.compiere.model;

import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;

import org.compiere.util.CCache;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.Env;

public class MCharge extends X_C_Charge{

/**
	 * 
	 */
//	private static final long serialVersionUID = 1L;
	private static final long serialVersionUID = 630271473830196435L;

	//	private Mbcsinputfinreportsline[] lines;
	private static CLogger s_log = CLogger.getCLogger(MCharge.class);
	
	
	public MCharge(Properties ctx, int C_Charge_ID,
			String trxName) {
		super (ctx, C_Charge_ID, trxName);
		if (C_Charge_ID == 0)
		{
			setChargeAmt (Env.ZERO);
			setIsSameCurrency (false);
			setIsSameTax (false);
			setIsTaxIncluded (false);	// N
		//	setName (null);
		//	setC_TaxCategory_ID (0);
		}
	}
	
	public MCharge(Properties ctx, ResultSet rs, String trxName){
		super(ctx, rs, trxName);
	}
	
	
	/**
	 *  Get Charge Account
	 *  @param C_Charge_ID charge
	 *  @param as account schema
	 *  @param amount amount for expense(+)/revenue(-)
	 *  @return Charge Account or null
	 */
	public static MAccount getAccount (int C_Charge_ID, MAcctSchema as, BigDecimal amount)
	{
		if (C_Charge_ID == 0 || as == null)
			return null;

		String acctName = X_C_Charge_Acct.COLUMNNAME_Ch_Expense_Acct;		//  Expense (positive amt)
		if (amount != null && amount.signum() < 0)
			acctName = X_C_Charge_Acct.COLUMNNAME_Ch_Revenue_Acct;			//  Revenue (negative amt)
		String sql = "SELECT "+acctName+" FROM C_Charge_Acct WHERE C_Charge_ID=? AND C_AcctSchema_ID=?";
		int Account_ID = DB.getSQLValueEx(null, sql, C_Charge_ID, as.get_ID());
		//	No account
		if (Account_ID <= 0)
		{
			s_log.severe ("NO account for C_Charge_ID=" + C_Charge_ID);
			return null;
		}

		//	Return Account
		MAccount acct = MAccount.get (as.getCtx(), Account_ID);
		return acct;
	}   //  getAccount

	/**
	 * 	Get MCharge from Cache
	 *	@param ctx context
	 *	@param C_Charge_ID id
	 *	@return MCharge
	 */
	public static MCharge get (Properties ctx, int C_Charge_ID)
	{
		Integer key = new Integer (C_Charge_ID);
		MCharge retValue = (MCharge)s_cache.get (key);
		if (retValue != null)
			return retValue;
		retValue = new MCharge (ctx, C_Charge_ID, null);
		if (retValue.get_ID() != 0)
			s_cache.put (key, retValue);
		return retValue;
	}	//	get

	/**	Cache						*/
	private static CCache<Integer, MCharge> s_cache 
		= new CCache<Integer, MCharge> ("C_Charge", 10);
	
	
	@Override
	protected boolean afterSave (boolean newRecord, boolean success)
	{
		if (newRecord && success)
			insert_Accounting("C_Charge_Acct", "C_AcctSchema_Default", null);

//		return success;
		
		if (newRecord)
		{
			String treeType = "CH";
			StringBuffer sb = new StringBuffer ("INSERT INTO ")
			.append(MTree_Base.getNodeTableName(treeType))
			.append(" (AD_Client_ID,AD_Org_ID, IsActive,Created,CreatedBy,Updated,UpdatedBy, "
				+ "AD_Tree_ID, Node_ID, Parent_ID, SeqNo) "
				+ "SELECT t.AD_Client_ID, 0, 'Y', SysDate, "+getUpdatedBy()+", SysDate, "+getUpdatedBy()+","
				+ "t.AD_Tree_ID, ").append(get_ID()).append(", 0, 999 "
				+ "FROM AD_Tree t "
				+ "WHERE t.AD_Client_ID=").append(getAD_Client_ID()).append(" AND t.IsActive='Y'");
		//	Account Element Value handling
//		if (C_Element_ID != 0)
//			sb.append(" AND EXISTS (SELECT * FROM C_Element ae WHERE ae.C_Element_ID=")
//				.append(C_Element_ID).append(" AND t.AD_Tree_ID=ae.AD_Tree_ID)");
//		else	//	std trees
			sb.append(" AND t.IsAllNodes='Y' AND t.TreeType='").append(treeType).append("'");
		//	Duplicate Check
		sb.append(" AND NOT EXISTS (SELECT * FROM " + MTree_Base.getNodeTableName(treeType) + " e "
				+ "WHERE e.AD_Tree_ID=t.AD_Tree_ID AND Node_ID=").append(get_ID()).append(")");
		int no = DB.executeUpdate(sb.toString(), get_TrxName());
		if (no > 0)
			log.fine("#" + no + " - TreeType=" + treeType);
		else
			log.warning("#" + no + " - TreeType=" + treeType);
		return no > 0;
			
			
//			String treeType = "BC";
//			String tableName = MTree_Base.getNodeTableName(treeType);
//			
//			final StringBuilder select = new StringBuilder("SELECT t.AD_Tree_ID FROM AD_Tree t WHERE t.AD_Client_ID=").append(getAD_Client_ID()).append(" AND t.IsActive='Y'"); 
////			if (C_Element_ID != 0)
////				select.append(" AND EXISTS (SELECT * FROM C_Element ae WHERE ae.C_Element_ID=")
////					.append(C_Element_ID).append(" AND t.AD_Tree_ID=ae.AD_Tree_ID)");
////			else	//	std trees
//				select.append(" AND t.IsAllNodes='Y' AND t.TreeType='").append(treeType).append("'");
//			//	Duplicate Check
//			select.append(" AND NOT EXISTS (SELECT * FROM " + MTree_Base.getNodeTableName(treeType) + " e "
//					+ "WHERE e.AD_Tree_ID=t.AD_Tree_ID AND Node_ID=").append(get_ID()).append(")");
//			int AD_Tree_ID = DB.getSQLValue(get_TrxName(), select.toString());
//			
//			PO tree = MTable.get(getCtx(), tableName).getPO(0, get_TrxName());
//			tree.setAD_Client_ID(getAD_Client_ID());
//			tree.setAD_Org_ID(0);
//			tree.setIsActive(true);
//			tree.set_CustomColumn("AD_Tree_ID",AD_Tree_ID);
//			tree.set_CustomColumn("Node_ID", get_ID());
//			tree.set_CustomColumn("Parent_ID", 0);
//			tree.set_CustomColumn("SeqNo", 999);
//			tree.saveEx();
//			return true;
			
			
			// afalcone [Bugs #1837219]
//			int ad_Tree_ID= (new MElement(getCtx(), getC_Element_ID(), get_TrxName())).getAD_Tree_ID();
//			String treeType= (new MTree(getCtx(),ad_Tree_ID,get_TrxName())).getTreeType();
//			insert_Tree(treeType, getC_Element_ID());
			//	insert_Tree(MTree_Base.TREETYPE_ElementValue, getC_Element_ID()); Old
			
		}
		
		//	Value/Name change
//		if (!newRecord && (is_ValueChanged(COLUMNNAME_Value) || is_ValueChanged(COLUMNNAME_Name)))
//		{
//			MAccount.updateValueDescription(getCtx(), "Account_ID=" + getC_ElementValue_ID(),get_TrxName());
//			if ("Y".equals(Env.getContext(getCtx(), "$Element_U1"))) 
//				MAccount.updateValueDescription(getCtx(), "User1_ID=" + getC_ElementValue_ID(),get_TrxName());
//			if ("Y".equals(Env.getContext(getCtx(), "$Element_U2"))) 
//				MAccount.updateValueDescription(getCtx(), "User2_ID=" + getC_ElementValue_ID(),get_TrxName());
//		}

		return success;
	}	//	afterSave
	
	
	protected boolean beforeSave(boolean newRecord){
//		int newValue = (int)get_Value("bcs_finreportspos_id");
//
//		int oldValue = 0;
//		
//		try{
//			oldValue = (int)get_ValueOld("bcs_finreportspos_id");
//		}catch(Exception e){};
//		
//		
//		if(newValue != oldValue){
//			int ID = get_ID();
//			
//		    PreparedStatement pstmt = null;
//			ResultSet rs = null;
//			MInvoice result = null;
//				
//			// delete all positions
//			String sqld = " DELETE FROM adempiere.bcs_inputfinreportsline \n " +
//					   " WHERE bcs_inputfinreports_id="  +  ID;
//
//			int no = DB.executeUpdate(sqld, get_TrxName());
//			
//			//create positions
//			String sql = 
//					  " SELECT \n"  
//					+ "		dictline.bcs_finreportsdictline_id \n"
//					+ "FROM adempiere.bcs_finreportspos head \n"
//					+ "inner join adempiere.bcs_finreportsposline line on line.bcs_finreportspos_id = head.bcs_finreportspos_id \n"
//					+ "inner join adempiere.bcs_finreportsdictline dictline on dictline.bcs_finreportsdictline_id = line.bcs_finreportsdictline_id \n"
//					+ "WHERE \n"
//					+ "	line.isactive='Y' \n" 
//					+ "	AND head.isactive='Y' \n"
//					+ "	AND dictline.isactive='Y' \n"
//					+ "	AND head.bcs_finreportspos_id = " + newValue; 
//					;
//
//				try{
//					pstmt = DB.prepareStatement(sql,null);				
//					rs = pstmt.executeQuery();	
//					while(rs.next()){
//						Mbcsinputfinreportsline m = new Mbcsinputfinreportsline(Env.getCtx(), 0, get_TrxName());
//						m.setbcs_inputfinreports_ID(ID);
//						m.setbcs_finreportsdictline_ID(rs.getInt(1));
//						m.save();
//					}
//				}catch (SQLException e){
//					s_log.log(Level.SEVERE, "product", e);
//				}finally{
//					DB.close(rs, pstmt);
//					rs = null; pstmt = null;
//				}			
//		}
		
//		System.out.println(getLines());
		return true;
	}
	
//	public boolean save(){
//		
//		return true;
//	};
	protected boolean beforeDelete ()
	{
		return delete_Accounting("C_Charge_Acct"); 
	}	//	beforeDelete
}
